﻿using System;
using System.Reflection;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;

using SBPweb.RIA.Shared.Contracts.Logging;

namespace SBPweb.RIA.Server.Logging.Log4Net
{

    public class LogManager : LogManagerBase
    {

        #region Private fields

        private log4net.ILog log;
        private string format = "[{0}]\t{1}:\t{2}";
        private ICollection<string> categories;

        #endregion

        #region Constructor logic

        public LogManager()
            : this(Assembly.GetEntryAssembly(), typeof(LogManager)) 
        {
        }

        public LogManager(Type type)
            : this(Assembly.GetEntryAssembly(), type)
        {
        }

        public LogManager(Assembly asm)
            : this(asm, typeof(LogManager))
        {
        }

        public LogManager(Assembly asm, Type type)
        {
            categories = new Collection<string>();
            categories.Add("Common");
            log = log4net.LogManager.GetLogger(asm, type);
        }

        #endregion

        #region Property accessors

        public override ICollection<string> Categories
        {
            get
            {
                return categories;
            }
        }

        public bool IsConfigured
        {
            get
            {
                return log.Logger.Repository.Configured;
            }
        }

        public FileInfo ConfigFile { get; set; }

        #endregion

        #region Methods

        protected override void OnInitialize()
        {
            if (ConfigFile != null && ConfigFile.Exists)
            {
                log4net.Config.XmlConfigurator.Configure(ConfigFile);
            }
            else
            {
                log4net.Config.XmlConfigurator.Configure();
            }
        }

        protected override void OnTerminate()
        {
            log.Logger.Repository.Shutdown();
        }

        protected override void OnWrite(object sender, SeverityLevel severity, object obj, string category)
        {
            base.OnWrite(sender, severity, obj, category);
            switch (severity)
            {
                default:
                case SeverityLevel.None:
                    break;
                case SeverityLevel.Critical:
                    if (log.IsFatalEnabled)
                    {
                        log.FatalFormat(format, category, sender, obj);
                    }
                    break;
                case SeverityLevel.Error:
                    if (log.IsErrorEnabled)
                    {
                        log.ErrorFormat(format, category, sender, obj);
                    }
                    break;
                case SeverityLevel.Information:
                    if (log.IsInfoEnabled)
                    {
                        log.InfoFormat(format, category, sender, obj);
                    }
                    break;
                case SeverityLevel.Verbose:
                    if (log.IsDebugEnabled)
                    {
                        log.DebugFormat(format, category, sender, obj);
                    }
                    break;
                case SeverityLevel.Warning:
                    if (log.IsWarnEnabled)
                    {
                        log.WarnFormat(format, category, sender, obj);
                    }
                    break;
            }
        }

        protected override void OnWrite(object sender, SeverityLevel severity, object obj, string category, string title, int priority, int eventId)
        {
            base.OnWrite(sender, severity, obj, category, title, priority, eventId);
            switch (severity)
            {
                default:
                case SeverityLevel.None:
                    break;
                case SeverityLevel.Critical:
                    if (log.IsFatalEnabled)
                    {
                        log.FatalFormat(format, category, sender, obj, title, priority, eventId);
                    }
                    break;
                case SeverityLevel.Error:
                    if (log.IsErrorEnabled)
                    {
                        log.ErrorFormat(format, category, sender, obj, title, priority, eventId);
                    }
                    break;
                case SeverityLevel.Information:
                    if (log.IsInfoEnabled)
                    {
                        log.InfoFormat(format, category, sender, obj, title, priority, eventId);
                    }
                    break;
                case SeverityLevel.Verbose:
                    if (log.IsDebugEnabled)
                    {
                        log.DebugFormat(format, category, sender, obj, title, priority, eventId);
                    }
                    break;
                case SeverityLevel.Warning:
                    if (log.IsWarnEnabled)
                    {
                        log.WarnFormat(format, category, sender, obj, title, priority, eventId);
                    }
                    break;
            }
        }

        #endregion

    }

}